<?php
    defined('M2_MICRO') or die('Direct Access to this location is not allowed.');

    /**
      * @desc Class for system operations
      * @package M2 Micro Framework
      * @author Alexander Chaika
      */
    class System extends Error {
        // instance
        private static $instance = null;
        
        // system config
        private $config = null;

        /**
          * System class constructor & clone
          * Use pattern singleton
          */
        private function __construct() {}
        private function __clone() {}

        /**
          * Return the instance of object
          * @param array $config (optional)
          */
        public static function getInstance() {
            // return instance
            if (null === self::$instance) {
                self::$instance = new self();
            }
            return self::$instance;
        }
        
        /**
          * Get Server config
          * @return array $config
          */
        public function getConfig() {
            // global config
            if ($this->config === null) {
                $result = $this->parseConfig();
                if (!$result) $this->throwError('Could not parse config file!');
            }

            // return config
            return $this->config;
        }

        /**
          * Get variable from Request
          * @param string $param
          * @param mixed  $default
          * @return mixed $value
          */
        public function getCmd($param, $default) {
            global $error;

            if (isset($_REQUEST[$param]) && !empty($_REQUEST[$param])) {
                if (!is_array($_REQUEST[$param])) {
                    return mysql_escape_string($_REQUEST[$param]);
                } else {
                    return array_map('mysql_escape_string', $_REQUEST[$param]);
                }
            }

            if (isset($_FILES[$param]) && !empty($_FILES[$param])) {
                if (count($_FILES[$param]['tmp_name']) > 0) {
                    $default = array();
                    while (list($key, $value) = each($_FILES[$param]["name"])) {
                        if ($_FILES[$param]["error"][$key] > 0) {
                            $this->throwError("Error transfer file [" . $_FILES[$param]["name"][$key] . ']!') ;
                        } else {
                            $file_parts  = pathinfo($_FILES[$param]['name'][$key]);
                            $allowed_ext = explode(',', $this->config['allowed_file_extentions']);

                            // check file extension
                            if (in_array(strtolower($file_parts['extension']), $allowed_ext)) {
                                $temp_file   = $_FILES[$param]['tmp_name'][$key];
                                $target_path = $this->config['doc_root'] . '/' . $this->config['upload_image_path'] . '/';

                                // generate unique name
                                $target_name = md5(mt_rand(0, 100).time()) . '.' . $file_parts['extension'];
                                $target_file = str_replace('//', '/', $target_path) . $target_name;

                                // move file to storage
                                if (!move_uploaded_file($temp_file, $target_file)) {
                                    $this->throwError('File upload failed ['.$_FILES[$param]["name"][$key].']. Please check permissions for writing.');
                                } else {
                                    $default[$_FILES[$param]["name"][$key]] = $target_name;
                                }
                            } else {
                                $this->throwError('Invalid file type ['.$_FILES[$param]['name'][$key].']!');
                            }
                        }
                    }
                    return $default;
                }
            }

            return $default;
        }

        /**
          * Send mail via standart PHP mailer
          * @param string $email
          * @param string $title
          * @param string $description
          * @return bool $state
          */
        public function mail($email, $title, $description, $attach = null) {
            // check email
            if ($this->isValidEmail($email)) {
                // mail headers & body
                if ($attach) {
                    $uid = strtoupper(uniqid(time()));
                    $headers  = "MIME-Version: 1.0\r\n";
                    $headers .= "X-Mailer: PHP/" . phpversion()."\n";
                    $headers .= "From: Kronenbourg <noreply@kronenbourg.com>\r\n";
                    $headers .= "Content-Type:multipart/mixed;";
                    $headers .= "boundary=\"----------".$uid."\"\n\n";

                    $desc  = "------------".$uid."\nContent-Type:text/html;\n";
                    $desc .= "Content-Transfer-Encoding: 8bit\n\n$description\n\n";
                    $desc .= "------------".$uid."\n";
                    $desc .= "Content-Type: application/octet-stream;";
                    $desc .= "name=\"".basename($attach)."\"\n";
                    $desc .= "Content-Transfer-Encoding:base64\n";
                    $desc .= "Content-Disposition:attachment;";
                    $desc .= "filename=\"".basename($attach)."\"\n\n";
                    $desc .= chunk_split(base64_encode(fread(fopen($attach, "rb"), filesize($attach))))."\n";
                } else {
                    $headers  = "MIME-Version: 1.0\r\n";
                    $headers .= "Content-type: text/html; charset=utf-8\r\n";
                    $headers .= "From: Kronenbourg <noreply@kronenbourg.com>\r\n";
                    $headers .= "X-Mailer: PHP/" . phpversion()."\n";

                    $desc = $description;
                }

                // try to send email
                try {
                    $result = mail($email, $title, $desc, $headers);

                    // send mail failed
                    if ($result) {
                        return $this->cleanError();
                    } else {
                        return $this->throwError('Send email failed!');
                    }
                } catch(Exception $e) {
                    return $this->throwError($e->getMessage());
                }
            } else {
                return false;
            }
        }

        /**
          * Create Thumbnail for image and store to thumbnails path
          * @param string $sname - source
          * @param string $dname - destination
          * @param int $width
          * @param int $height
          * @param int $mode (optional: 0 - with aspect ratio, other - head-on)
          * @return bool $result
          */
        public function createThumbnail($sname, $dname, $width, $height, $mode = 0) {
            // create source
            switch (strtolower(strrchr($sname, '.'))) {
                case '.jpg':
                    $source = imagecreatefromjpeg($sname);
                    break;
                case '.gif':
                    $source = imagecreatefromgif($sname);
                    break;
                case '.png':
                    $source = imagecreatefrompng($sname);
                    break;
                default:
                    return $this->throwError('This is not a image!');
            }

            // get source dimensions
            $swidth = imagesx($source);
            $sheight = imagesy($source);

            try {
                // check if dest dimensions larger than source
                if (($width < $swidth) || ($height < $sheight)) {
                    if ($mode == 0) { // save aspect ratio
                        $ratiox = $swidth / $width;
                        $ratioy = $sheight / $height;

                        if ($ratiox < $ratioy) {
                            $dwidth  = intval($swidth / $ratioy);
                            $dheight = $height;
                        } else {
                            $dwidth  = $width;
                            $dheight = intval($sheight / $ratiox);
                        }
                    } else {
                        $dheight = $height;
                        $dwidth  = $width;
                    }

                    // create destination resource
                    $dest = imagecreatetruecolor($dwidth, $dheight);

                    // create destination image file
                    imagecopyresampled($source, $dest, 0, 0, 0, 0, $dwidth, $dheight, $swidth, $sheight);
                    imagejpeg($dest, $dname, 90); // 100 - максимальное качество

                    // delete resources
                    imagedestroy($source);
                    imagedestroy($dest);
                } else {
                    // if dest dimensions larger than source
                    // simply copy source file
                    copy($sname, $dname);
                }
            } catch (Exception $e) {
                return $this->throwError($e->getMessage());
            }

            return $this->cleanError();
        }


        /**
          * Email validation
          * @param string $email
          * @return bool $valid
          */
        public function isValidEmail($email) {
            return true;
            $regexp = '/^[a-z_0-9\-\.]+@[a-z_0-9\-\.]+\.[a-z]{2,6}$/i';
            if (!preg_match($regexp, $email)) return $this->throwError('Invalid Email!');
            else return $this->cleanError();
        }

        /**
          * Parse config from INI file
          * @return bool $state
          */
        private function parseConfig() {
            $config = parse_ini_file('config.ini');

            if (!empty($config)) {
                // parse config to object
                foreach($config as $key => $value) {
                    $this->config[$key] = $value;
                }

                // define http_host & doc_root if empty
                if (empty($this->config['http_host'])) {
                    $this->config['http_host']  = 'http://' . $_SERVER['HTTP_HOST'];
                }

                if (empty($this->config['doc_root'])) {
                    $this->config['doc_root']   = $_SERVER['DOCUMENT_ROOT'];
                }

                return $this->cleanError();
            } else {
                return $this->throwError('Could not parse config!');
            }
        }
    }

    // global object
    $GLOBALS['system'] = $system = System::getInstance();
    $GLOBALS['config'] = $system->getConfig();
?>
